﻿using DiffuseEnjoyIdle.Model.Config;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using RabbitMQ.Client;
using System.Text;

namespace DiffuseEnjoyIdle.MessageCenter.RabbitMQ
{
    public class RabbitMQServer
    {
        private readonly ILogger<RabbitMQServer> _logger;
        private readonly IModel _channel;

        public RabbitMQServer(IOptions<RabbitMQConfig> options
            , ILogger<RabbitMQServer> logger
            , List<Tuple<string, string, string, IDictionary<string, object>>> tuples)
        {
            var rabbitMqConfig = options.Value;
            _logger = logger;


            ConnectionFactory factory = new ConnectionFactory
            {
                UserName = rabbitMqConfig.UserName,
                Password = rabbitMqConfig.Password,
                HostName = rabbitMqConfig.HostName,
                Port = rabbitMqConfig.Port,
                VirtualHost = rabbitMqConfig.VirtualHost
            };

            var connection = factory.CreateConnection();

            _channel = connection.CreateModel();

            foreach (var (exchangeName, queueName, routingKey, arguments) in tuples)
            {
                QueueBind(exchangeName, queueName, routingKey, arguments);
            }
        }

        public void PushMessage(string exchangeName, string routingKey, object message, string exchangeType = ExchangeType.Fanout)
        {
            //TODO:exchangeType未使用
            _logger.LogInformation($"PushMessage,routingKey:{routingKey}");

            var msg = message is string ? message.ToString() : JsonConvert.SerializeObject(message);

            var body = Encoding.UTF8.GetBytes(msg ?? string.Empty);

            _channel.BasicPublish(exchangeName, routingKey, null, body);
        }

        private void QueueBind(string exchangeName, string queueName, string routingKey, IDictionary<string, object> arguments = null)
        {
            _channel.ExchangeDeclare(exchangeName, ExchangeType.Direct, true);
            _channel.QueueDeclare(queueName, true, false, false, arguments);
            _channel.QueueBind(queueName, exchangeName, routingKey, arguments);
        }
    }
}
